package com.start.ws;

import com.alibaba.fastjson2.JSONObject;
import com.start.common.tools.SpringContextTools;
import com.start.ws.connect.StartConnectLifeCycle;
import com.start.ws.connect.StartConnectManager;
import com.start.ws.handler.StartBaseSocketMsgHandler;
import com.start.ws.msg.StartBaseMessage;
import jakarta.websocket.Session;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;

import java.util.Collection;
import java.util.HashMap;
import java.util.Map;

@Slf4j
@Component(StartGlobalSocketDispatcher.NAME)
public class StartGlobalSocketDispatcher implements StartConnectLifeCycle, StartBaseSocketMsgHandler<JSONObject> {
    public static final String NAME = "StartGlobalSocketDispatcher" ;

    private Map<String, StartBaseSocketMsgHandler> msgServiceMap = null;
    private static StartGlobalSocketDispatcher dispatcher;

    public static StartGlobalSocketDispatcher getDispatcher() {
        if (dispatcher == null) {
            dispatcher = SpringContextTools.getBean(StartGlobalSocketDispatcher.class);
        }
        return dispatcher;
    }

    public StartGlobalSocketDispatcher() {
        Map<String, StartBaseSocketMsgHandler> beans = null;
        try {
            beans = SpringContextTools.getBeans(StartBaseSocketMsgHandler.class);
        } catch (Exception e) {
            e.printStackTrace();
        }

        if (beans == null || beans.isEmpty()) {
            return;
        }
        Collection<StartBaseSocketMsgHandler> values = beans.values();
        msgServiceMap = new HashMap<>();
        for (StartBaseSocketMsgHandler value : values) {
            if (NAME.equals(value.handlerMsgType())) {
                continue;
            }
            msgServiceMap.put(value.handlerMsgType(), value);
        }
    }

    public void onConnect(String startUserType, String clientType, String userId, Session session) {
        StartConnectManager.getInstance().onConnect(startUserType, clientType, userId, session);
    }


    @Override
    public void onReceive(String startUserType, String sendClientType, String userId, JSONObject msg) {
        onReceive(startUserType, sendClientType, userId, msg, msg.getString("clientMsgId"));
    }

    /**
     * 接收到消息
     *
     * @param startUserType
     * @param sendClientType  发送人客户类型
     * @param userId          发送人用户id
     * @param msg             消息内容
     * @param sendClientMsgId 发送人客户端消息id
     */
    @Override
    public void onReceive(String startUserType, String sendClientType, String userId, JSONObject msg, String sendClientMsgId) {
        if (msgServiceMap == null) {
            log.warn("未找到消息处理器:");
            return;
        }
        StartBaseMessage baseMessage = msg.toJavaObject(StartBaseMessage.class);
        if (StringUtils.isEmpty(baseMessage.getMsgContent())) {
            log.info("消息内容不能为空：clientId:{}\nuserId:{}\nmsg:{}", sendClientType, userId, msg);
            return;
        }
        if (StringUtils.isEmpty(baseMessage.getMsgHandlerType())) {
            log.info("消息处理器：clientId:{}\nuserId:{}\nmsg:{}", sendClientType, userId, msg);
            return;
        }
        if (!msgServiceMap.containsKey(baseMessage.getMsgHandlerType())) {
            log.info("消息处理器：clientId:{}\nuserId:{}\nmsg:{}", sendClientType, userId, msg);
            return;
        }
        StartBaseSocketMsgHandler startBaseSocketMsgHandler = msgServiceMap.get(baseMessage.getMsgHandlerType());
        Object formatMsg = startBaseSocketMsgHandler.formatMsg(baseMessage.getMsgContent());
        startBaseSocketMsgHandler.onReceive(startUserType, sendClientType, userId, formatMsg, baseMessage.getClientMsgId());
    }

    @Override
    public String handlerMsgType() {
        return NAME;
    }

    @Override
    public JSONObject formatMsg(String msg) {
        return JSONObject.parseObject(msg);
    }

    public void onClose(String startUserType, String clientType, String userId, Session session) {
        StartConnectManager.getInstance().onClose(startUserType, clientType, userId, session);
    }
}
